package io.ede.modules.ede.service.impl;

import io.ede.common.exception.RRException;
import io.ede.common.utils.*;
import io.ede.modules.ede.dao.GroupDao;
import io.ede.modules.ede.dao.ModelDao;
import io.ede.modules.ede.entity.GroupEntity;
import io.ede.modules.ede.entity.ModelEntity;
import io.ede.modules.ede.entity.SysAttrConfigEntity;
import io.ede.modules.oss.cloud.OSSFactory;
import io.ede.modules.sys.dao.SysUserDao;
import io.ede.modules.sys.entity.SysUserEntity;
import io.ede.modules.sys.shiro.ShiroUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import io.ede.modules.ede.dao.ProjectDao;
import io.ede.modules.ede.entity.ProjectEntity;
import io.ede.modules.ede.service.ProjectService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


@Service("projectService")
public class ProjectServiceImpl extends ServiceImpl<ProjectDao, ProjectEntity> implements ProjectService {

    @Autowired
    private ProjectDao projectDao;
    @Autowired
    private ModelDao modelDao;
    @Autowired
    private GroupDao groupDao;
    @Autowired
    private SysUserDao sysUserDao;

    @Value("${project.path}")
    public String path;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<ProjectEntity> page = this.page(
                new Query<ProjectEntity>().getPage(params),
                new QueryWrapper<ProjectEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 上传工程
     *
     * @param
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean importPorject(MultipartFile file, String suffix) throws Exception {
        //获取用户信息
        SysUserEntity userEntity = ShiroUtils.getUserEntity();
        //解压文件
        Map map = new HashMap();
        if(".zip".equals(suffix)){
            InputStream in = file.getInputStream();
            map = ZipUtils.unZip(in);
        }else {
            String fileName = file.getOriginalFilename();
            //ie下fileName包含盘符，去掉盘符
            if(fileName.contains(File.separator)){
                fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
            }
            fileName = fileName.replace(".rar","");
            String filePath = path + "/" + userEntity.getUserId() + "/" + fileName ;
            File file2 = new File(filePath);
            if(!file2.exists()){
                file2.mkdirs();
            }
            File _filePath = new File(filePath+"/"+fileName+suffix);
            file.transferTo(_filePath);
            //解压
            RarUtils.realExtract(_filePath,filePath);
            //读取目录下所有文件
            File fileAll = new File(filePath);
            RarUtils.getFileList(fileAll.getPath()+"\\",fileAll,map);
        }

        //存储动作组py文件（排序）
        SortedMap<String, Object> sortedMapPy = new TreeMap<String, Object>();
        //存储动作组xml文件（排序）
        SortedMap<String, Object> sortedMapXml = new TreeMap<String, Object>();
        //存储音乐

        //工程id
        Integer projectId = null;
        //工程实体
        ProjectEntity project = new ProjectEntity();

        for (Object keyObj : map.keySet()) {
            String key = keyObj.toString();
            byte[] value = (byte[]) map.get(keyObj);
            //读取工程名称
            if (key.contains(".fii") && ZipUtils.appearNumber(key, "/") == 1) {
                String[] projectNames = key.split("/");
                String fii = new String(value);
                System.out.println("工程名称：" + projectNames[0]);
                System.out.println("fii文件内容：" + new String(value, StandardCharsets.UTF_8));
                //校验工程名称是否存在
                boolean isExit = this.isExitProject(projectNames[0]);
                if (isExit) {
                    throw new RRException("工程已经存在！");
                }
                //获取工程信息
                this.getProjectInfo(fii, project);
                project.setProject(projectNames[0]);
                project.setFii(new String(value, StandardCharsets.UTF_8));
                project.setCreateTime(new Date());
                project.setUserId(Integer.parseInt(userEntity.getUserId() + ""));
            }
            //读取工作组py文件
            if (key.contains("webCodeAll.py") && key.contains("动作组") && ZipUtils.appearNumber(key, "/") == 3) {
                //System.out.println("文件名：" + key);
                //System.out.println("文件内容：" + new String(value));
                sortedMapPy.put(key, new String(value));
            }
            //读取工作组xml文件
            if (key.contains("webCodeAll.xml") && key.contains("动作组") && ZipUtils.appearNumber(key, "/") == 3) {
                //System.out.println("文件名：" + key);
                //System.out.println("文件内容：" + new String(value));
                sortedMapXml.put(key, new String(value));
            }
            //读取工作组mp3文件
            if(key.contains(".mp3") && key.contains("动作组") && ZipUtils.appearNumber(key, "/") == 2 ) {
                String url = OSSFactory.build().uploadSuffix(value, ".mp3");
                //音乐大小
                project.setSpace(value.length/1024);
                //音乐路径
                project.setMusic(url);
                //音乐名称
                project.setMusicName(key.substring(key.lastIndexOf("/")+1));
            }
        }

        //保存工程
        projectDao.insert(project);
        projectId = project.getId();

        //重新计算用户已经使用的空间
        this.updUserSpace();

        //保存工作组
        for (String key : sortedMapPy.keySet()) {
            System.out.println("文件名：" + key);
            String xmlKey = key.replace("webCodeAll.py", "webCodeAll.xml");
            System.out.println("文件名：" + xmlKey);
            String[] keys = key.split("/");
            GroupEntity groupEntity = new GroupEntity();
            groupEntity.setName(keys[2]);
            groupEntity.setProjectId(projectId);
            groupEntity.setCreateTime(new Date());
            groupEntity.setPy(sortedMapPy.get(key).toString());
            groupEntity.setXml(sortedMapXml.get(xmlKey).toString());
            groupDao.insert(groupEntity);
        }
        return true;
    }

    /**
     * 获取工程信息
     *
     * @param xml
     * @param project
     * @return
     */
    public ProjectEntity getProjectInfo(String xml, ProjectEntity project) {
        SAXReader reader = new SAXReader();
        Document document;
        try {
            document = reader.read(new ByteArrayInputStream(xml.getBytes("utf-8")));
            //获取root(根)节点
            Element root = document.getRootElement();
            //设备类型
            List<Element> deviceTypes = XmlParser.getNameElement(root, "DeviceType");
            if (deviceTypes.size() > 0) {
                Element deviceType = deviceTypes.get(0);
                String deviceTypeDes = XmlParser.attrValue(deviceType, "DeviceType");
                // 去机型表查找ID
                Map<String, Object> param = new HashMap<>();
                param.put("model", deviceTypeDes);
                param.put("del_flag", "1");
                List<ModelEntity> modelList = modelDao.selectByMap(param);
                if (modelList != null && modelList.size() > 0) {
                    Integer id = modelList.get(0).getId();
                    project.setModelId(id);
                }
            }
            //场地大小 - 长
            List<Element> areaLs = XmlParser.getNameElement(root, "AreaL");
            if (areaLs.size() > 0) {
                Element areaL = areaLs.get(0);
                String areaLDes = XmlParser.attrValue(areaL, "AreaL");
                project.setAreaL(areaLDes);
            }
            //场地大小 - 宽
            List<Element> areaWs = XmlParser.getNameElement(root, "AreaW");
            if (areaLs.size() > 0) {
                Element areaW = areaWs.get(0);
                String areaWDes = XmlParser.attrValue(areaW, "AreaW");
                project.setAreaW(areaWDes);
            }
            //场地大小 - 高
            List<Element> areaHs = XmlParser.getNameElement(root, "AreaH");
            if (areaLs.size() > 0) {
                Element areaH = areaHs.get(0);
                String areaHDes = XmlParser.attrValue(areaH, "AreaH");
                project.setAreaH(areaHDes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return project;
    }

    //验证工程是否存在
    public boolean isExitProject(String projectName) {
        //获取用户信息
        SysUserEntity userEntity = ShiroUtils.getUserEntity();
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userEntity.getUserId());
        map.put("del_flag", "1");
        map.put("project", projectName);
        List<ProjectEntity> projectList = projectDao.selectByMap(map);
        if (projectList != null && projectList.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 保存工程
     *
     * @param group
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveProject(GroupEntity group) {
        Map<String, Object> map = new HashMap<>();
        map.put("project_id", group.getProjectId());
        map.put("name", group.getName());
        map.put("del_flag", "1");
        List<GroupEntity> groupList = groupDao.selectByMap(map);
        if (groupList.size() == 1) {
            GroupEntity gp = groupList.get(0);
            gp.setPy(group.getPy());
            gp.setXml(group.getXml());
            groupDao.updateById(gp);
        }
        //获取动作组配置
        String xml = group.getXml();
        System.out.println(xml);
        SAXReader reader = new SAXReader();
        Document document;
        try {
            document = reader.read(new ByteArrayInputStream(xml.getBytes("utf-8")));
            //获取root(根)节点
            Element root = document.getRootElement();
            //再动态添加
            List<Element> fieldList = XmlParser.getNameElement(root, "field");

            //获取fii文件
            ProjectEntity project = projectDao.selectById(group.getProjectId());
            String fii = project.getFii();

            Document fiiDocument = reader.read(new ByteArrayInputStream(fii.getBytes("utf-8")));
            //获取root(根)节点
            Element fiiRoot = fiiDocument.getRootElement();
            //先删除时间节点
            XmlParser.deleteElement(fiiRoot, group.getName() + "Controls");
            for (Element ele : fieldList) {
                String name = XmlParser.attrValue(ele, "name");
                if ("time".equals(name)) {
                    //获取时间
                    String time = ele.getText();
                    if (time.contains(":")) {
                        String[] times = time.split(":");
                        String mini = times[0];
                        String secs = times[1];
                        Integer total = Integer.parseInt(mini) * 60 + Integer.parseInt(secs);
                        String controls = "<" + group.getName() + "Controls time=\"" + total + "\"/>";
                        System.out.println(controls);
                        XmlParser.addElement(fiiRoot, group.getName() + "Controls", "time", total + "", "");
                    }
                }
            }
            //修改fii
            project.setFii(fiiDocument.asXML());
            projectDao.updateById(project);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 新建工程
     *
     * @param project
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(ProjectEntity project) {
        //保存工程
        projectDao.insert(project);
        //新建动作组
        String xml = "<xml xmlns=\"http://www.w3.org/1999/xhtml\">"
                + " <variables></variables>"
                + " <block type=\"Goertek_Start\" x=\"100\" y=\"20\"></block>"
                + "</xml>";
        GroupEntity group = new GroupEntity();
        group.setProjectId(project.getId());
        group.setName("动作组1");
        group.setPy("Start()");
        group.setXml(xml);
        group.setCreateTime(new Date());
        groupDao.insert(group);
        return false;
    }

    @Override
    public List<ProjectEntity> selectByMap(Map<String, Object> params) {
        return this.list(new QueryWrapper<ProjectEntity>()
                .eq("user_id", params.get("user_id"))
                .eq("del_flag", params.get("del_flag"))
                .orderByDesc("create_time")
        );
    }

    /**
     * 计算用户使用空间
     */
    @Override
    public void updUserSpace() {
        SysUserEntity userEntity = ShiroUtils.getUserEntity();
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userEntity.getUserId());
        map.put("del_flag", "1");
        List<ProjectEntity> projectList = projectDao.selectByMap(map);
        Integer space = 0;
        for (ProjectEntity project : projectList) {
            if (project.getSpace() != null) {
                space += project.getSpace();
            }
        }
        SysAttrConfigEntity sysAttrConfigEntity = SysAttrConfigConstant.sysAttrConfigEntity;
        String totalSpace = sysAttrConfigEntity.getSpace();
        Integer total = StringUtils.isNotEmpty(totalSpace) ? Integer.parseInt(totalSpace) : 0;
        if (space > total * 1024) {
            throw new RRException("空间不足，无法新建工程！");
        }
        SysUserEntity user = new SysUserEntity();
        user.setUserId(userEntity.getUserId());
        user.setSpace(space);
        sysUserDao.updateById(user);
        //修改缓存中的空间
        userEntity.setSpace(space);
    }


}
